package org.wdcode.base.dao.spring.hibernate;

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.wdcode.base.bean.PageBean;

import org.wdcode.common.util.CommonUtil;
import org.wdcode.core.dao.spring.hibernate.BasicHibernateDao;

/**
 * 对BasicHibernateDao的扩展,添加了一些实用方法,比如分页
 * @see org.wdcode.common.dao.spring.hibernate.BasicHibernateDao
 * @author WD
 * @since JDK6
 * @version 1.0 2009-09-01
 */
public final class ExtendHibernateDao extends BasicHibernateDao {
	/**
	 * 获得查询的对象实体列表 分页功能
	 * @param exampleEntity 需要获得的对象，会查询出实体中封装的相等的条件
	 * @param page 分页Bean
	 * @return 返回这个对象的列表
	 */
	public final <E> List<E> queryByExample(E exampleEntity, PageBean page) {
		// 获得数据列表
		List<E> list = queryByExample(exampleEntity, getFirstResult(page), getMaxResults(page));
		// 判断列表
		if (CommonUtil.isEmpty(list)) {
			// 为空 设置总数为 0
			page.setTotalSize(0);
		} else {
			// 不为空 查询出总数
			page.setTotalSize(queryByExampleForCount(exampleEntity));
		}
		// 返回列表
		return list;
	}

	/**
	 * 根据HQL查询语句查询
	 * @param queryString HQL查询语句 参数为?的语句
	 * @param page 分页Bean
	 * @param value 参数列表 *
	 * @return 返回结果列表
	 */
	public final <E> List<E> query(String queryString, PageBean page, List<Object> value) {
		return query(queryString, page, value.toArray());
	}

	/**
	 * 根据HQL查询语句查询
	 * @param queryString HQL查询语句 参数为?的语句
	 * @param page 分页Bean
	 * @param values 参数数组 *
	 * @return 返回结果列表
	 */
	public <E> List<E> query(String queryString, PageBean page, Object... values) {
		// 获得数据列表
		List<E> list = query(queryString, values, getFirstResult(page), getMaxResults(page));
		// 判断列表
		if (CommonUtil.isEmpty(list)) {
			// 为空 设置总数为 0
			page.setTotalSize(0);
		} else {
			// 不为空 查询出总数
			page.setTotalSize(queryForCount(queryString, values));
		}
		// 返回列表
		return list;
	}

	/**
	 * 根据SQL查询语句查询
	 * @param queryString SQL查询语句 参数为?的语句
	 * @param value 参数列表
	 * @param page 分页Bean
	 * @return 返回结果列表
	 */
	public final <E> List<E> querySQL(String queryString, PageBean page, List<Object> value) {
		return querySQL(queryString, page, value.toArray());
	}

	/**
	 * 根据SQL查询语句查询
	 * @param queryString SQL查询语句 参数为?的语句
	 * @param values 参数数组
	 * @param page 分页Bean
	 * @return 返回结果列表
	 */
	public final <E> List<E> querySQL(String queryString, PageBean page, Object... values) {
		// 获得数据列表
		List<E> list = querySQL(queryString, values, getFirstResult(page), getMaxResults(page));
		// 判断列表
		if (CommonUtil.isEmpty(list)) {
			// 为空 设置总数为 0
			page.setTotalSize(0);
		} else {
			// 不为空 查询出总数
			page.setTotalSize(querySQLForCount(queryString, values));
		}
		// 返回列表
		return list;
	}

	/**
	 * 根据HQL查询语句查询
	 * @param queryString HQL查询语句 参数为:name的语句
	 * @param param 参数列表 key对应:name,value对应值，这个Map不能为空
	 * @return 返回结果列表
	 */
	public final <E> List<E> queryByNamedParam(String queryString, PageBean page, Map<String, Object> param) {
		// 获得Key数组
		String[] keys = parseMapToKey(param);
		// 调用方法
		return queryByNamedParam(queryString, page, keys, parseMapToValue(param, keys));
	}

	/**
	 * 根据HQL查询语句查询
	 * @param queryString HQL查询语句 参数为:name的语句
	 * @param paramNames 参数名
	 * @param values 参数值
	 * @return 返回结果列表
	 */
	public <E> List<E> queryByNamedParam(String queryString, PageBean page, String[] paramNames, Object... values) {
		// 获得数据列表
		List<E> list = queryByNamedParam(queryString, paramNames, values, getFirstResult(page), getMaxResults(page));
		// 判断列表
		if (CommonUtil.isEmpty(list)) {
			// 为空 设置总数为 0
			page.setTotalSize(0);
		} else {
			// 不为空 查询出总数
			page.setTotalSize(queryByNamedParamForCount(queryString, paramNames, values));
		}
		// 返回列表
		return list;
	}

	/**
	 * 查询hbm文件定义的查询名称 语句需用 :name 做条件
	 * @param queryName 查询名称
	 * @param param 参数Map key对应:name,value对应值，这个Map不能为空
	 * @param page 分页Bean
	 * @return 返回结果列表
	 */
	public final <E> List<E> queryByNamedQueryAndNamedParam(String queryName, PageBean page, Map<String, Object> param) {
		// 获得Key数组
		String[] keys = parseMapToKey(param);
		// 调用方法
		return queryByNamedQueryAndNamedParam(queryName, page, keys, parseMapToValue(param, keys));
	}

	/**
	 * 查询hbm文件定义的查询名称 语句需用 :name 做条件
	 * @param queryName 查询名称
	 * @param paramNames 参数名
	 * @param values 参数值
	 * @param page 分页Bean
	 * @return 返回结果列表
	 */
	public <E> List<E> queryByNamedQueryAndNamedParam(String queryName, PageBean page, String[] paramNames, Object... values) {
		// 获得数据列表
		List<E> list = queryByNamedQueryAndNamedParam(queryName, paramNames, values, getFirstResult(page), getMaxResults(page));
		// 判断列表
		if (CommonUtil.isEmpty(list)) {
			// 为空 设置总数为 0
			page.setTotalSize(0);
		} else {
			// 不为空 查询出总数
			page.setTotalSize(queryByNamedQueryAndNamedParamForCount(queryName, paramNames, values));
		}
		// 返回列表
		return list;
	}

	/**
	 * 执行非查询的HQL语言 使用 :name 做参数
	 * @param hql hql语句 不能是查询的
	 * @param param 参数列表 key对应:name,value对应值，这个Map不能为空
	 * @return 返回影响的行数
	 */
	public final int executeByParam(String hql, Map<String, Object> param) {
		// 获得Key数组
		String[] keys = parseMapToKey(param);
		// 调用方法
		return executeByParam(hql, keys, parseMapToValue(param, keys));
	}

	/**
	 * 执行hbm文件定义的非查询语句 语句需用 :name 做条件
	 * @param name 语句名称
	 * @param param 参数Map key对应:name,value对应值，这个Map不能为空
	 * @return 返回结果列表
	 */
	public final int executeByNamedAndParam(String name, Map<String, Object> param) {
		// 获得Key数组
		String[] keys = parseMapToKey(param);
		// 调用方法
		return executeByNamedAndParam(name, keys, parseMapToValue(param, keys));
	}

	/**
	 * 根据HQL查询语句查询
	 * @param queryString HQL查询语句 参数为:name的语句
	 * @param param 参数列表 key对应:name,value对应值，这个Map不能为空
	 * @return 返回结果列表
	 */
	public final <E> List<E> queryByNamedParam(String queryString, Map<String, Object> param) {
		// 获得Key数组
		String[] keys = parseMapToKey(param);
		// 调用自己的方法返回
		return queryByNamedParam(queryString, keys, parseMapToValue(param, keys));
	}

	/**
	 * 查询hbm文件定义的查询名称 语句需用 :name 做条件
	 * @param queryName 查询名称
	 * @param param 参数Map key对应:name,value对应值，这个Map不能为空
	 * @return 返回结果列表
	 */
	public final <E> List<E> queryByNamedQueryAndNamedParam(String queryName, Map<String, Object> param) {
		// 获得Key数组
		String[] keys = parseMapToKey(param);
		// 调用自己的方法返回
		return queryByNamedQueryAndNamedParam(queryName, keys, parseMapToValue(param, keys));
	}

	/**
	 * 执行非查询的HQL语言 使用 :name 做参数
	 * @param sql sql语句 不能是查询的
	 * @param param 参数列表 key对应:name,value对应值，这个Map不能为空
	 * @return 返回影响的行数
	 */
	public final int executeSQLByParam(String sql, Map<String, Object> param) {
		// 获得Key数组
		String[] keys = parseMapToKey(param);
		// 调用自己的方法返回
		return executeSQLByParam(sql, keys, parseMapToValue(param, keys));
	}

	/**
	 * 查询hbm文件定义的查询名称 语句需用 ? 做条件
	 * @param queryName 查询名称
	 * @param value 参数值
	 * @param page 分页Bean
	 * @return 返回结果列表
	 */
	public final <E> List<E> queryByNamedQuery(String queryName, PageBean page, List<Object> value) {
		return queryByNamedQuery(queryName, page, value.toArray());
	}

	/**
	 * 查询hbm文件定义的查询名称 语句需用 ? 做条件
	 * @param queryName 查询名称
	 * @param values 参数值数组
	 * @param page 分页Bean
	 * @return 返回结果列表
	 */
	public final <E> List<E> queryByNamedQuery(String queryName, PageBean page, Object... values) {
		// 获得数据列表
		List<E> list = queryByNamedQuery(queryName, values, getFirstResult(page), getMaxResults(page));
		// 判断列表
		if (CommonUtil.isEmpty(list)) {
			// 为空 设置总数为 0
			page.setTotalSize(0);
		} else {
			// 不为空 查询出总数
			page.setTotalSize(queryByNamedQueryForCount(queryName, values));
		}
		// 返回列表
		return list;
	}

	/**
	 * 查询字段在lo到hi之间的实体
	 * @param entity 查询实体
	 * @param page 分页实体
	 * @param propertyName 字段名
	 * @param lo 开始条件
	 * @param hi 结束条件
	 * @return 返回结果列表
	 */
	public <E> List<E> queryByBetween(E entity, PageBean page, String propertyName, Object lo, Object hi) {
		return queryByBetween(entity, page, new String[] { propertyName }, new Object[] { lo }, new Object[] { hi });
	}

	/**
	 * 查询字段在lo到hi之间的实体
	 * @param entity 查询实体
	 * @param page 分页实体
	 * @param propertyName 字段名
	 * @param lo 开始条件
	 * @param hi 结束条件
	 * @return 返回结果列表
	 */
	public <E> List<E> queryByBetween(E entity, PageBean page, String[] propertyName, Object[] lo, Object[] hi) {
		// 获得数据列表
		List<E> list = queryByBetween(entity, propertyName, lo, hi, getFirstResult(page), getMaxResults(page));
		// 判断列表
		if (CommonUtil.isEmpty(list)) {
			// 为空 设置总数为 0
			page.setTotalSize(0);
		} else {
			// 不为空 查询出总数
			page.setTotalSize(queryByBetweenForCount(entity, propertyName, lo, hi));
		}
		// 返回列表
		return list;
	}

	/**
	 * 解析Map 获得Key数组
	 * @param param map参数
	 * @return Key数组
	 */
	private String[] parseMapToKey(Map<String, Object> param) {
		// 获得参数列表的key集合
		Set<String> set = param.keySet();
		// 声明一个和key集合一样大小的字符串数组 参数名
		String[] keys = new String[set.size()];
		// 声明数组下标重0开始，用于给数组赋值
		int i = 0;
		// 循环遍历key集合
		for (String key : set) {
			// 参数名
			keys[i] = key;
			// i自加
			i++;
		}
		// 返回
		return keys;
	}

	/**
	 * 解析Map 获得value数组
	 * @param param map参数
	 * @param keys Key数组
	 * @return Value 数组
	 */
	private Object[] parseMapToValue(Map<String, Object> param, String[] keys) {
		// 声明数组对象 保存Value值
		Object[] values = new Object[keys.length];
		// 循环Key
		for (int i = 0; i < keys.length; i++) {
			// 获得Value
			values[i] = param.get(keys[i]);
		}
		// 返回Value数组
		return values;
	}

	/**
	 * 获得最大结果数
	 * @param page 分页Bean
	 * @return 最大结果数
	 */
	private int getMaxResults(PageBean page) {
		return CommonUtil.isEmpty(page) ? 0 : page.getPageSize();
	}

	/**
	 * 获得从第N条开始返回结果
	 * @param page 分页Bean
	 * @return 从第N条开始返回结果
	 */
	private int getFirstResult(PageBean page) {
		return CommonUtil.isEmpty(page) ? 0 : (page.getCurrentPage() - 1) * page.getPageSize();
	}
}
